<?php

namespace app\api\service;

use app\api\dao\WeChatZftDao;
use app\api\exception\ApiException;
use app\api\model\WeChatMerchant;
use app\common\constant\ErrorCode;
use app\service\OcrService;
use think\facade\Db;
use think\facade\Log;

/**
 * 微信商户业务服务类
 */
class WeChatMerchantService
{
    private WeChatZftDao $dao;
    private OcrService $ocrService;

    public function __construct()
    {
        $this->dao = new WeChatZftDao(0);
        $this->ocrService = new OcrService();
    }

    /**
     * 获取商户列表
     */
    public function getMerchantList(array $params): array
    {
        try {
            $openid = $params['openid'] ?? '';
            $page = $params['page'] ?? 1;
            $pageSize = $params['page_size'] ?? 10;
            $status = $params['status'] ?? '';

            // 构建查询条件
            $where = ['openid' => $openid];
            if (!empty($status)) {
                $where['status'] = $status;
            }

            // 获取分页数据
            $result = $this->dao->getPagesLists($where, $page, $pageSize);

            // 处理数据格式
            if ($result && isset($result['data'])) {
                foreach ($result['data'] as &$item) {
                    // 检查申请状态
                    if (in_array($item['status'], [
                        WeChatMerchant::STATUS['SUBMITTED'], 
                        WeChatMerchant::STATUS['TO_BE_SIGNED'], 
                        WeChatMerchant::STATUS['TO_BE_CONFIRMED']
                    ])) {
                        $item = $this->dao->getApplyStatus($item);
                    }
                    $item = $this->dao->getTranslate($item);
                    $item = $this->formatMerchantData($item);
                }
            }

            return $result;

        } catch (\Exception $e) {
            Log::error('获取商户列表失败: ' . $e->getMessage());
            throw new ApiException(
                '获取商户列表失败',
                ErrorCode::BUSINESS_ERROR
            );
        }
    }

    /**
     * 获取商户详情
     */
    public function getMerchantDetail(int $id, string $openid): array
    {
        try {
            $merchant = $this->dao->getDetails($id);
            
            if (empty($merchant)) {
                throw new ApiException(
                    ErrorCode::getMessage(ErrorCode::MERCHANT_NOT_FOUND),
                    ErrorCode::MERCHANT_NOT_FOUND,
                    404
                );
            }

            // 验证数据权限
            if ($merchant['openid'] !== $openid) {
                throw new ApiException(
                    ErrorCode::getMessage(ErrorCode::AUTH_PERMISSION_DENIED),
                    ErrorCode::AUTH_PERMISSION_DENIED,
                    403
                );
            }

            // 检查申请状态
            if (in_array($merchant['status'], [
                WeChatMerchant::STATUS['SUBMITTED'], 
                WeChatMerchant::STATUS['TO_BE_SIGNED'], 
                WeChatMerchant::STATUS['TO_BE_CONFIRMED']
            ])) {
                $merchant = $this->dao->getApplyStatus($merchant);
            }

            $merchant = $this->dao->getTranslate($merchant);
            return $this->formatMerchantData($merchant);

        } catch (ApiException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('获取商户详情失败: ' . $e->getMessage());
            throw new ApiException(
                '获取商户详情失败',
                ErrorCode::BUSINESS_ERROR
            );
        }
    }

    /**
     * 创建商户进件
     */
    public function createMerchant(array $data): array
    {
        // 开启事务
        return Db::transaction(function () use ($data) {
            try {
                // 1. 数据验证
                $this->validateMerchantData($data);

                // 2. 检查是否已存在
                $existing = $this->dao->findByCondition([
                    'openid' => $data['openid'],
                    'business_license_number' => $data['business_license_number']
                ]);

                if (!empty($existing)) {
                    throw new ApiException(
                        ErrorCode::getMessage(ErrorCode::MERCHANT_ALREADY_EXISTS),
                        ErrorCode::MERCHANT_ALREADY_EXISTS
                    );
                }

                // 3. 设置默认值
                $data['status'] = 'draft';
                $data['create_time'] = time();
                $data['update_time'] = time();

                // 4. 保存数据
                $result = $this->dao->add($data);

                // 5. 记录操作日志
                $this->logMerchantOperation('create', $result['id'] ?? 0, $data);

                return $result;

            } catch (ApiException $e) {
                throw $e;
            } catch (\Exception $e) {
                Log::error('创建商户失败: ' . $e->getMessage());
                throw new ApiException(
                    '创建商户失败',
                    ErrorCode::BUSINESS_ERROR
                );
            }
        });
    }

    /**
     * 更新商户信息
     */
    public function updateMerchant(int $id, array $data): array
    {
        return Db::transaction(function () use ($id, $data) {
            try {
                // 1. 检查商户是否存在
                $merchant = $this->dao->getDetails($id);
                if (empty($merchant)) {
                    throw new ApiException(
                        ErrorCode::getMessage(ErrorCode::MERCHANT_NOT_FOUND),
                        ErrorCode::MERCHANT_NOT_FOUND,
                        404
                    );
                }

                // 2. 验证数据权限
                if ($merchant['openid'] !== $data['openid']) {
                    throw new ApiException(
                        ErrorCode::getMessage(ErrorCode::AUTH_PERMISSION_DENIED),
                        ErrorCode::AUTH_PERMISSION_DENIED,
                        403
                    );
                }

                // 3. 检查状态是否允许修改
                if (!$this->canModifyMerchant($merchant['status'])) {
                    throw new ApiException(
                        '当前状态不允许修改',
                        ErrorCode::MERCHANT_STATUS_ERROR
                    );
                }

                // 4. 数据验证
                $this->validateMerchantData($data, $id);

                // 5. 更新数据
                $data['update_time'] = time();
                $result = $this->dao->edit($id, $data);

                // 6. 记录操作日志
                $this->logMerchantOperation('update', $id, $data);

                return $result;

            } catch (ApiException $e) {
                throw $e;
            } catch (\Exception $e) {
                Log::error('更新商户失败: ' . $e->getMessage());
                throw new ApiException(
                    '更新商户失败',
                    ErrorCode::BUSINESS_ERROR
                );
            }
        });
    }

    /**
     * 处理图片OCR识别
     */
    public function processImageOcr(string $imageUrl, string $type): array
    {
        try {
            return $this->dao->imageOcrAndCode($imageUrl, $type);
        } catch (\Exception $e) {
            Log::error('图片OCR识别失败: ' . $e->getMessage());
            throw new ApiException(
                '图片识别失败，请重新上传',
                ErrorCode::OCR_RECOGNITION_ERROR
            );
        }
    }

    /**
     * 获取银行支行列表
     */
    public function getBankBranches(string $bankName): array
    {
        try {
            return $this->dao->bankAccount(['name' => $bankName]);
        } catch (\Exception $e) {
            Log::error('获取银行支行失败: ' . $e->getMessage());
            throw new ApiException(
                '获取银行支行信息失败',
                ErrorCode::BANK_INFO_ERROR
            );
        }
    }

    /**
     * 获取组织机构列表
     */
    public function getOrgList(): array
    {
        try {
            return $this->dao->orgList();
        } catch (\Exception $e) {
            Log::error('获取组织机构列表失败: ' . $e->getMessage());
            throw new ApiException(
                '获取组织机构列表失败',
                ErrorCode::BUSINESS_ERROR
            );
        }
    }

    /**
     * 获取行业列表
     */
    public function getIndustryList(): array
    {
        try {
            return $this->dao->industryList();
        } catch (\Exception $e) {
            Log::error('获取行业列表失败: ' . $e->getMessage());
            throw new ApiException(
                '获取行业列表失败',
                ErrorCode::BUSINESS_ERROR
            );
        }
    }

    /**
     * 设置收款账户
     */
    public function setReceivingAccount(int $id, int $isPayAccount): array
    {
        try {
            return $this->dao->setReceivingAccount($id, $isPayAccount);
        } catch (\Exception $e) {
            Log::error('设置收款账户失败: ' . $e->getMessage());
            throw new ApiException(
                '设置收款账户失败',
                ErrorCode::BUSINESS_ERROR
            );
        }
    }

    /**
     * 验证商户数据
     */
    private function validateMerchantData(array $data, int $excludeId = 0): void
    {
        // 验证必要字段
        $requiredFields = [
            'merchant_name', 'business_license_number', 'legal_person',
            'id_card_number', 'mobile', 'email'
        ];

        foreach ($requiredFields as $field) {
            if (empty($data[$field])) {
                throw new ApiException(
                    "字段 {$field} 不能为空",
                    ErrorCode::PARAM_MISSING
                );
            }
        }

        // 验证身份证号格式
        if (!validateIdCard($data['id_card_number'])) {
            throw new ApiException(
                '身份证号格式不正确',
                ErrorCode::PARAM_INVALID
            );
        }

        // 验证手机号格式
        if (!isMobile($data['mobile'])) {
            throw new ApiException(
                '手机号格式不正确',
                ErrorCode::PARAM_INVALID
            );
        }

        // 验证邮箱格式
        if (!isEmail($data['email'])) {
            throw new ApiException(
                '邮箱格式不正确',
                ErrorCode::PARAM_INVALID
            );
        }
    }

    /**
     * 格式化商户数据
     */
    private function formatMerchantData(array $data): array
    {
        // 隐藏敏感信息
        if (isset($data['id_card_number'])) {
            $data['id_card_number_masked'] = maskString($data['id_card_number'], 6, 4);
        }
        
        if (isset($data['mobile'])) {
            $data['mobile_masked'] = maskString($data['mobile'], 3, 4);
        }

        // 添加状态描述
        $data['status_text'] = $this->getStatusText($data['status'] ?? '');

        // 格式化时间
        if (isset($data['create_time'])) {
            $data['create_time_text'] = date('Y-m-d H:i:s', $data['create_time']);
        }

        if (isset($data['update_time'])) {
            $data['update_time_text'] = date('Y-m-d H:i:s', $data['update_time']);
        }

        return $data;
    }

    /**
     * 获取状态描述
     */
    private function getStatusText(string $status): string
    {
        $statusMap = [
            'draft' => '草稿',
            'submitted' => '已提交',
            'auditing' => '审核中',
            'approved' => '已通过',
            'rejected' => '已拒绝',
            'to_be_signed' => '待签约',
            'to_be_confirmed' => '待确认',
        ];

        return $statusMap[$status] ?? '未知状态';
    }

    /**
     * 检查是否可以修改商户信息
     */
    private function canModifyMerchant(string $status): bool
    {
        return in_array($status, ['draft', 'rejected']);
    }

    /**
     * 记录商户操作日志
     */
    private function logMerchantOperation(string $action, int $merchantId, array $data): void
    {
        logs('商户操作记录', [
            'action' => $action,
            'merchant_id' => $merchantId,
            'data_keys' => array_keys($data),
            'timestamp' => date('Y-m-d H:i:s'),
        ]);
    }
}
